package com.juanLL.CMC;

import android.graphics.Canvas;
import android.util.Log;

import com.juanLL.CMC.models.GameWorld;
import com.juanLL.CMC.view.GameView;

/**
 * 
 * @author JJ Clase GameLoop se encarga de manejar el loop principal del juego y
 *         regular FPS
 */
public class GameLoop extends Thread {

	// Max number of FPS allowed
	private static final int MAX_FPS = 50;
	// Max number of frame skips allowed
	private static final int MAX_FRAME_SKIPS = 5;
	// Ammount of time it should ideally take to display MAX FPS
	private static final int FRAME_PERIOD = 1000 / MAX_FPS;

	// GameView object
	private GameView gameView;
	// GameWorld object
	private GameWorld gameWorld;
	// controls execution of game loop
	private boolean run = false;

	// Canvas object to draw on
	Canvas c;

	// aux var that aids in calculating the timeDiff
	long beginTime;
	// stores the amount of time it took to execute the loop
	long timeDiff;
	// stores the amount of time the thread will sleep
	int sleepTime;
	// stores the amount of frames skipped
	int framesSkipped;

	/**
	 * Constructor
	 * 
	 * @param gameView
	 *            View class on which the drawing is triggered.
	 * @param gameWorld
	 *            the class which handles the game logic
	 */
	public GameLoop(GameView gameView, GameWorld gameWorld) {
		this.gameView = gameView;
		this.gameWorld = gameWorld;
	}

	/**
	 * setRunning method, sets the value of the boolean variable that controls
	 * the execution of the game loop.
	 * 
	 * @param run
	 *            should the game run?
	 */
	public void setRunning(boolean run) {
		this.run = run;
	}

	/**
	 * 
	 * @return whether the game loop is running or not.
	 */
	public boolean isRunning() {
		return run;
	}

	/**
	 * Perform the game loop. Order of performing: 1. update GameWorld 2. Draw
	 * everything.
	 * 
	 */
	@Override
	public void run() {
		sleepTime = 0;
		while (run) {
			try {
				c = gameView.getHolder().lockCanvas(null);
				synchronized (gameView.getHolder()) {
					beginTime = System.currentTimeMillis();
					framesSkipped = 0;
					// update game state
					gameWorld.update();
					// draw game state
					gameView.onDraw(c);
					timeDiff = System.currentTimeMillis() - beginTime;
					sleepTime = (int) (FRAME_PERIOD - timeDiff);

					if (sleepTime > 0) {
						try {
							GameLoop.sleep(sleepTime);
						} catch (InterruptedException e) {

						}
					}
					// skip frame and update the game state without drawing
					while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
						// update game state
						gameWorld.update();
						sleepTime += FRAME_PERIOD;
						framesSkipped++;
						Log.d("GAME", "SKIP");
					}

				}
			} finally {
				if (c != null) {
					gameView.getHolder().unlockCanvasAndPost(c);
				}
			}
		}
	}

	public void onPause() {
		AssetLoader.music.pause();
		this.setRunning(false);
	}

}
